#pragma once 
#include <iostream>
#include <string>
#include <vector>
#include "Util.hpp"
using namespace std;


//协议
namespace protocol_ns{

    //运算式分隔符
    #define SEP " "
    //运算式分割符长度
    #define SEP_LEN strlen(SEP)

    //报头及有效载荷分割符
    #define HEADER_SEP "\r\n"
    //报文及有效载荷分割符长度
    #define HEADER_SEP_LEN strlen("\r\n")
    //格式：
    //"长度\r\n_x _op _y\r\n" = 报头+有效载荷
    
    //把数据封装成数据报
    string AddHeader(const string &str){
        string s = to_string(str.size());
        s += HEADER_SEP;
        s += str;
        s += HEADER_SEP;
        return s;
    }

    //从数据报中提取出有效载荷
    string RemoveHeader(const string &str, int len){
        //从后往前算起始位置
        return str.substr(str.size() - HEADER_SEP_LEN - len, len);
    }

    int ReadPackage(int sock, string& inbuf, string *package){
        //读取
        char buf[1024];
        ssize_t s = recv(sock, buf, sizeof(buf - 1), 0);
        if(s<=0){
            return -1;
        }
        buf[s] = 0;
        inbuf += buf;

        //检测
        //检查是否有分割符，收否收到完整报头
        auto pos = inbuf.find(HEADER_SEP);
        if(pos == string::npos){
            return 0;
        }
        //找到分割符后这个分割符一定在报头后面，获取报头字符串
        string len_str = inbuf.substr(0, pos);
        //有效载荷的长度
        int len = Util::toInt(len_str);
        //报文长度package_len = 报头除分割符的长度 + 有效载荷除分割符的长度 + 两个报文分割符的长度
        int package_len = len_str.size() + len + 2 * HEADER_SEP_LEN;
        //数据载荷不完整
        if(inbuf.size()<package_len){
            return 0;
        }

        //走到这里，报头和数据载荷都是完整的，进行提取
        *package = inbuf.substr(0, package_len);
        //清空inbuf -- err，可能后面还有数据
        // inbuf = "";
        //移除已经提取的数据
        inbuf.erase(0, package_len);
        return len;
    }

    class Request{
    public:

        Request(){}

        Request(int x, int y, char op): _x(x), _y(y), _op(op) {

        }

        ~Request(){
            
        }

        //序列化struct -> string
        bool Serialize(string* ostr){
            //清空ostr
            *ostr = "";
            string x_string = to_string(_x);
            string y_string = to_string(_y);

            *ostr += x_string + SEP + _op + SEP + y_string;
            return true;
        }

        //反序列化string -> struct
        //把string拆解，存到自己里面
        bool DesSerialize(const string& istr){
            vector<string> res;
            Util::StringSplit(istr, SEP, &res);
            if(res.size()==3 && res[1].size() == 1){
                _x = Util::toInt(res[0]); 
                _y = Util::toInt(res[2]);
                _op = res[1][0];
            }else{
                return false;
            }
            return true;
        }

    public:
        //
        int _x;
        int _y;
        char _op;
    };

    class Response{
    public:

        Response(){}

        Response(int result, int code): _result(result), _code(code) {
            
        }   

        ~Response(){
            
        }

        //序列化struct -> string
        bool Serialize(string* ostr){
            //_result _code
            *ostr = "";
            *ostr = to_string(_result) + SEP + to_string(_code);

            return true;
        }


        //反序列化string -> struct
        //把string拆解，存到自己里面
        bool DesSerialize(const string& istr){
            vector<string> res;
            Util::StringSplit(istr, SEP, &res);
            if(res.size()==2){
                _result = Util::toInt(res[0]); 
                _code = Util::toInt(res[1]);
            }else{
                return false;
            }
            return true;
        }

    public:
        int _result;
        int _code;  //默认为0，表示成功
    };
}

